package com.imis.base.util.form;

import com.imis.base.constant.CommonConstant;
import com.imis.base.util.ConvertUtils;
import com.imis.module.online.form.model.po.FormButton;
import com.imis.module.online.form.model.po.FormEnhanceJavaScript;
import com.imis.module.online.table.model.po.TableFields;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 * EnhanceJavaScriptUtil<br>
 * JavaScript 增强工具类
 * </p>
 *
 * @author XinLau
 * @version 1.0
 * @since 2019年03月26日 11:11
 */
@Slf4j
public class EnhanceJavaScriptUtil {

    /**
     * 增强 JavaScript 按钮代码
     */
    private static final String[] ENHANCE_JAVA_SCRIPT_BUTTON_CODE = {"beforeAdd", "beforeEdit", "afterAdd", "afterEdit", "beforeDelete", "afterDelete", "mounted", "created", "show"};

    /**
     * 第二个方法 前面是}，需要替换成},
     */
    private static final String SECOND_FUN_PRE = "\\}\\s*\r*\n*\\s*";

    /**
     * 根据 Pattern 替换字符串
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param patternString     - 正则表达式
     * @param replaceString     - 替换
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    private static String replaceJavaScriptByPatternCanNull(String enhanceJavaScript, final String patternString, final String replaceString) {
        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(enhanceJavaScript);
        if (matcher.find()) {
            enhanceJavaScript = enhanceJavaScript.replace(matcher.group(0), replaceString);
            return enhanceJavaScript;
        } else {
            return null;
        }
    }

    /**
     * 字段 Change 事件的 JavaScript 增强
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param fieldName         - 字段名称
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    private static String replaceFieldChangeJavaScript(String enhanceJavaScript, final String fieldName) {
        String patternString = "(\\s+" + fieldName + "\\s*\\(\\)\\s*\\{)";
        String replaceString = fieldName + ":function(that,event){";
        String temp = replaceJavaScriptByPatternCanNull(enhanceJavaScript, SECOND_FUN_PRE + patternString, "}," + replaceString);
        if (temp == null) {
            enhanceJavaScript = replaceJavaScriptByPattern(enhanceJavaScript, patternString, replaceString);
        } else {
            enhanceJavaScript = temp;
        }
        return enhanceJavaScript;
    }

    /**
     * 操作列上的按钮</br>
     * <ul>
     *     <li>将buttonCode(){ 替换成 buttonCode:function(){</li>
     *     <li>将buttonCode(row){ 替换成 buttonCode:function(row){</li>
     * </ul>
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param buttonCode        - 按钮代码
     * @return String - enhanceJavaScript
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/19 8:23
     */
    public static String replaceLinkButtonJavaScript(String enhanceJavaScript, String buttonCode) {
        String patternString = "(" + buttonCode + "\\s*\\(row\\)\\s*\\{)";
        String replaceString = buttonCode + ":function(that,row){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;";
        String temp = replaceJavaScriptByPatternCanNull(enhanceJavaScript, SECOND_FUN_PRE + patternString, "}," + replaceString);
        if (temp == null) {
            enhanceJavaScript = replaceJavaScriptByPattern(enhanceJavaScript, patternString, replaceString);
        } else {
            enhanceJavaScript = temp;
        }
        enhanceJavaScript = replaceCommonButtonJavaScript(enhanceJavaScript, buttonCode, null);
        return enhanceJavaScript;
    }

    /**
     * 列表上方按钮 表单按钮
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param buttonCode        - 按钮代码
     * @param prefixPattern     - 前缀正则
     * @return String - enhanceJavaScript
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/19 8:23
     */
    public static String replaceCommonButtonJavaScript(String enhanceJavaScript, String buttonCode, String prefixPattern) {
        String patternString = "(" + ConvertUtils.getString(prefixPattern) + buttonCode + "\\s*\\(\\)\\s*\\{)";
        String replaceString = buttonCode + ":function(that){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;";
        String temp = replaceJavaScriptByPatternCanNull(enhanceJavaScript, SECOND_FUN_PRE + patternString, "}," + replaceString);
        if (temp == null) {
            enhanceJavaScript = replaceJavaScriptByPattern(enhanceJavaScript, patternString, replaceString);
        } else {
            enhanceJavaScript = temp;
        }
        return enhanceJavaScript;
    }

    /**
     * 根据 Pattern 替换 JavaScript 增强
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param patternString     - 正则表达式
     * @param replaceString     - 替换
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static String replaceJavaScriptByPattern(String enhanceJavaScript, String patternString, String replaceString) {
        String temp = replaceJavaScriptByPatternCanNull(enhanceJavaScript, patternString, replaceString);
        if (temp != null) {
            return temp;
        }
        return enhanceJavaScript;
    }

    /**
     * 表单页面的 JavaScript 增强格式化方法
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static String getFormEnhanceJavaScript(String enhanceJavaScript) {
        log.info("最终的增强 JavaScript", enhanceJavaScript);
        return "class OnlineEnhanceJavaScript{constructor(getAction,postAction,deleteAction){this._getAction=getAction;this._postAction=postAction;this._deleteAction=deleteAction;}" + enhanceJavaScript + "}";
    }

    /**
     * 列表/表单 页面的 JavaScript 增强格式化方法
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static String theLastJavaScriptEnhanceString(String enhanceJavaScript) {
        String theLastJavaScriptEnhanceString = "function OnlineEnhanceJavaScript(getAction,postAction,deleteAction){return {_getAction:getAction,_postAction:postAction,_deleteAction:deleteAction," + enhanceJavaScript + "}}";
        log.info("最终的增强 JavaScript", theLastJavaScriptEnhanceString);
        return theLastJavaScriptEnhanceString;
    }

    /**
     * 列表/表单 页面的 JavaScript 增强格式化方法
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param formButtonList    - 表单按钮
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static String overFinalWriteJavaScript(String enhanceJavaScript, List<FormButton> formButtonList) {
        enhanceJavaScript = overwriteClearButton(enhanceJavaScript, formButtonList);
        String theLastJavaScriptEnhanceString = "function OnlineEnhanceJavaScript(getAction,postAction,deleteAction){return {_getAction:getAction,_postAction:postAction,_deleteAction:deleteAction," + enhanceJavaScript + "}}";
        log.info("最终的增强 JavaScript:", theLastJavaScriptEnhanceString);
        return theLastJavaScriptEnhanceString;
    }

    /**
     * 覆盖清除按钮
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param formButtonList    - 表单按钮
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static String overwriteClearButton(String enhanceJavaScript, List<FormButton> formButtonList) {
        if (formButtonList != null) {
            for (FormButton button : formButtonList) {
                String buttonCode = button.getButtonCode();
                if (CommonConstant.ONLINE_BUTTON_STYLE_LINK.equals(button.getButtonStyle())) {
                    enhanceJavaScript = replaceLinkButtonJavaScript(enhanceJavaScript, buttonCode);
                } else if (CommonConstant.ONLINE_BUTTON_STYLE_BUTTON.equals(button.getButtonStyle()) || CommonConstant.ONLINE_BUTTON_STYLE_FORM.equals(button.getButtonStyle())) {
                    enhanceJavaScript = replaceCommonButtonJavaScript(enhanceJavaScript, buttonCode, null);
                }
            }
        }
        for (String temp : ENHANCE_JAVA_SCRIPT_BUTTON_CODE) {
            if ("beforeAdd,afterAdd,mounted,created,show".indexOf(temp) >= 0) {
                enhanceJavaScript = replaceCommonButtonJavaScript(enhanceJavaScript, temp, null);
            } else {
                enhanceJavaScript = replaceLinkButtonJavaScript(enhanceJavaScript, temp);
            }
        }
        return enhanceJavaScript;
    }

    /**
     * 数据库表 JavaScript 增强生成（change方法命名： onlineChange）
     *
     * @param formEnhanceJavaScript - 表单 JavaScript 增强
     * @param tableName             - 数据库表名称
     * @param tableFieldsList       - 数据库表字段信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static void overwriteJavaScriptForTable(FormEnhanceJavaScript formEnhanceJavaScript, final String tableName, final List<TableFields> tableFieldsList) {
        if (formEnhanceJavaScript == null || ConvertUtils.isEmpty(formEnhanceJavaScript.getJavaScriptContent())) {
            return;
        }
        // 先加个空格，防止正则匹配不到这种情况 =>（ JavaScript 增强直接以 onlineChange 开头对齐）
        String enhanceJavaScript = CommonConstant.SPACE + formEnhanceJavaScript.getJavaScriptContent();
        log.info("TableEnhanceJavaScriptBegin ==> " + enhanceJavaScript);
        // 处理主表 onlineChange 方法 【change方法命名： onlineChange】
        Pattern pattern = Pattern.compile("(\\s{1}" + CommonConstant.ONLINE_JAVA_SCRIPT_CHANGE_FUNCTION_NAME + "\\s*\\(\\)\\s*\\{)");
        Matcher matcher = pattern.matcher(enhanceJavaScript);
        if (matcher.find()) {
            log.info("--- JavaScript 增强转换 - Table - enhanceJavaScriptFunctionName ----" + CommonConstant.ONLINE_JAVA_SCRIPT_CHANGE_FUNCTION_NAME);
            enhanceJavaScript = replaceCommonButtonJavaScript(enhanceJavaScript, CommonConstant.ONLINE_JAVA_SCRIPT_CHANGE_FUNCTION_NAME, "\\s{1}");
            for (TableFields tableFields : tableFieldsList) {
                // 字段 Change 事件 TODO:This 主表 和 子表有，重名的字段会出问题
                enhanceJavaScript = replaceFieldChangeJavaScript(enhanceJavaScript, tableFields.getFieldName());
            }
        }
        log.info("TableEnhanceJavaScriptEnd ==> " + enhanceJavaScript);
        formEnhanceJavaScript.setJavaScriptContent(enhanceJavaScript);
    }

    /**
     * 数据库表子表 JavaScript 增强生成（change方法命名： {子表名}_onlineChange）
     *
     * @param formEnhanceJavaScript - 表单 JavaScript 增强
     * @param tableName             - 数据库表名称
     * @param tableFieldsList       - 数据库表字段信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static void overwriteJavaScriptForChildTable(FormEnhanceJavaScript formEnhanceJavaScript, final String tableName, final List<TableFields> tableFieldsList) {
        if (formEnhanceJavaScript == null || ConvertUtils.isEmpty(formEnhanceJavaScript.getJavaScriptContent())) {
            return;
        }
        log.info("ChildTableEnhanceJavaScriptBegin ==> " + formEnhanceJavaScript);
        String enhanceJavaScript = formEnhanceJavaScript.getJavaScriptContent();
        // 子表 change JavaScript 方法名字
        String enhanceJavaScriptFunctionName = tableName + "_" + CommonConstant.ONLINE_JAVA_SCRIPT_CHANGE_FUNCTION_NAME;
        // 转换子表主 change 方法和字段方法 TODO：This 子表表名命名，有包含匹配的会有问题
        Pattern pattern = Pattern.compile("(" + enhanceJavaScriptFunctionName + "\\s*\\(\\)\\s*\\{)");
        Matcher matcher = pattern.matcher(enhanceJavaScript);
        if (matcher.find()) {
            log.info("--- JavaScript 增强转换 - ChildTable - enhanceJavaScriptFunctionName ---" + enhanceJavaScriptFunctionName);
            enhanceJavaScript = replaceCommonButtonJavaScript(enhanceJavaScript, enhanceJavaScriptFunctionName, null);
            for (TableFields tableFields : tableFieldsList) {
                // 字段 Change 事件 TODO：This  主表和子表有，重名的字段会出问题
                enhanceJavaScript = replaceFieldChangeJavaScript(enhanceJavaScript, tableFields.getFieldName());
            }
        }
        log.info("ChildTableEnhanceJavaScriptEnd ==> " + enhanceJavaScript);
        formEnhanceJavaScript.setJavaScriptContent(enhanceJavaScript);
    }

}
